<?php

/**
 * procedure actions.
 *
 * @package    BuLaBuSys2013
 * @subpackage procedure
 * @author     Maximilian Lenkeit
 * @version    SVN: $Id: actions.class.php 23810 2009-11-12 11:07:44Z Kris.Wallsmith $
 * @TODO Add where necessary:
    if(!$request->isMethod('post')) {
      throw new Exception();
    }
 */
class procedureActions extends sfActions
{

  /**
   *
   * @param sfRequest $request A request object
   */
  public function executeHowto (sfWebRequest $request)
  {
    
  }

  /**
   *
   * @param sfRequest $request A request object
   */
  public function executeAboutMe (sfWebRequest $request)
  {
    $this->initilizeProcedure();
    $this->getProcedure()->setUser($this->getUser()->getGuardUser());
    $this->form = new AboutMeForm($this->getProcedure()
      ->getUserProfile());
  }

  /**
   *
   * @param sfRequest $request A request object
   */
  public function executeAboutMeToParticipants (sfWebRequest $request)
  {
    if ($this->processAboutMe($request))
    {
      $this->redirect($this->generateUrl('procedure_2_participants'));
    }
    else
    {
      $this->setTemplate('aboutMe');
    }
  }

  /**
   *
   * @param sfRequest $request A request object
   */
  public function executeParticipants (sfWebRequest $request)
  {
    $this->getLogger()->debug(sprintf('Calling %s', __METHOD__));
    $this->form = new DynamicParticipantForm($this->getProcedure()
      ->getParticipants(), array(
      DynamicParticipantForm::OPTION_PARTICIPANT_DEFAULT_VALUES => $this->getProcedure()
      ->getParticipantDefaultValues(),
      DynamicParticipantForm::OPTION_LOGGER => $this->getLogger()));
  }

  public function executeParticipantsToAboutMe (sfWebRequest $request)
  {
    $this->getLogger()->debug(sprintf('Calling %s', __METHOD__));
    
    if ($this->processParticipants($request))
    {
      $this->redirect($this->generateUrl('procedure_1_about_me'));
    }
    else
    {
      $this->setTemplate('participants');
    }
  }

  public function executeParticipantsToTents (sfWebRequest $request)
  {
    $this->getLogger()->debug(sprintf('Calling %s', __METHOD__));
    
    if ($request->getParameter('addRow') == 1)
    {
      return $this->executeParticipantsAddRow($request);
    }
    
    if ($this->processParticipants($request))
    {
      $this->redirect($this->generateUrl('procedure_3_tents'));
    }
    else
    {
      $this->setTemplate('participants');
    }
  }

  public function executeParticipantsAddRow (sfWebRequest $request)
  {
    $this->getLogger()->debug(sprintf('Calling %s', __METHOD__));
    
    $participants = $this->getProcedure()->getParticipants();
    $num_participants_in_house = 0;
    $num_participants_in_tent = 0;
    // TODO refactor as method to procedure
    foreach($participants as $participant) {
      if($participant->getAccomodation() == 'h') {
        $num_participants_in_house++;
      } else {
        $num_participants_in_tent++;
      }
    }
    
    $this->form = new DynamicParticipantForm($this->getProcedure()
      ->getParticipants(), array(
      DynamicParticipantForm::OPTION_PARTICIPANT_DEFAULT_VALUES => $this->getProcedure()
      ->getParticipantDefaultValues(),
      DynamicParticipantForm::OPTION_LOGGER => $this->getLogger()));
    
    $this->form->addPreviouslyAddedForms($request->getParameter($this->form->getName()));  
    $this->form->addForm();
    $this->form->bind($request->getParameter($this->form->getName()), $request->getFiles($this->form->getName()));
    
    $this->setTemplate('participants');
  }

  /**
   *
   * @param sfRequest $request A request object
   */
  public function executeTents (sfWebRequest $request)
  {
    $participants = $this->getProcedure()->getParticipants();
    $num_participants_in_house = 0;
    $num_participants_in_tent = 0;
    // TODo refactor as method to procedure
    foreach($participants as $participant) {
      if($participant->getAccomodation() == 'h') {
        $num_participants_in_house++;
      } else {
        $num_participants_in_tent++;
      }
    }
    
    $tents = $this->getProcedure()
      ->getTents();
      $house_found = false;
    foreach($tents as $tent) {
      if($tent->getType() == 'h') {
        $house_found = true;
        $tent->setCapacity($num_participants_in_house);
      }
    }
    if(!$house_found && $num_participants_in_house > 0) {
      $tent = new Tent();
      $tent->setType('h');
      $tent->setCapacity($num_participants_in_house);
      $tents->add($tent);
    }
    
    $this->form = new DynamicTentForm($tents);
    $this->num_participants_in_house = $num_participants_in_house;
    $this->num_participants_in_tent = $num_participants_in_tent;
  }

  public function executeTentsToAboutMe (sfWebRequest $request)
  {
    if ($this->processTents($request))
    {
      $this->redirect($this->generateUrl('procedure_1_about_me'));
    }
    else
    {
      $this->setTemplate('tents');
    }
  }

  public function executeTentsToParticipants (sfWebRequest $request)
  {
    if ($this->processTents($request))
    {
      $this->redirect($this->generateUrl('procedure_2_participants'));
    }
    else
    {
      $this->setTemplate('tents');
    }
  }

  public function executeTentsToOverview (sfWebRequest $request)
  {
    if ($request->getParameter('addRow') == 1)
    {
      return $this->executeTentsAddRow($request);
    }
    
    if ($this->processTents($request))
    {
      $this->redirect($this->generateUrl('procedure_4_overview'));
    }
    else
    {
      $this->setTemplate('tents');
    }
  }

  public function executeTentsAddRow (sfWebRequest $request)
  {
    $participants = $this->getProcedure()->getParticipants();
    $num_participants_in_house = 0;
    $num_participants_in_tent = 0;
    // TODo refactor as method to procedure
    foreach($participants as $participant) {
      if($participant->getAccomodation() == 'h') {
        $num_participants_in_house++;
      } else {
        $num_participants_in_tent++;
      }
    }
    $this->num_participants_in_house = $num_participants_in_house;
    $this->num_participants_in_tent = $num_participants_in_tent;
    
    
    $this->form = new DynamicTentForm($this->getProcedure()
      ->getTents());
    
    $this->form->addPreviouslyAddedForms($request->getParameter($this->form->getName()));
    $this->form->addForm();
    $this->form->bind($request->getParameter($this->form->getName()), $request->getFiles($this->form->getName()));
    
    $this->setTemplate('tents');
  }

  /**
   *
   * @param sfRequest $request A request object
   */
  public function executeOverview (sfWebRequest $request)
  {
    $procedure = $this->getProcedure();
    $this->about_me = $procedure->getUserProfile();
    $this->participants = $procedure->getParticipants();
    $this->tents = $procedure->getTents();
    
    if($procedure->isFirstTime()) {
      $this->calculator = new PriceCalculator(new Doctrine_Collection('Booking'), new Doctrine_Collection('Payment'), $this->participants);
    } else {
      // TODO Refactor
      $bookings = new Doctrine_Collection('Booking');
      $bookings->add($this->getUser()->getGuardUser()->getBooking());
      $payments = $this->getUser()->getGuardUser()->getBooking()->getPayments();
      $this->calculator = new PriceCalculator($bookings, $payments, $this->participants);
    }
  }

  /**
   *
   * @param sfRequest $request A request object
   */
  public function executeSave (sfWebRequest $request)
  {
    $this->executeOverview($request);
    $procedure = $this->getProcedure();
    
    $this->getLogger()->debug('Beginning transaction...');
    $conn = $this->getContext()->getDatabaseManager()->getDatabase('doctrine')->getDoctrineConnection(); 
    $old_transaction_type_attribute = $conn->getAttribute(Doctrine_Core::ATTR_AUTOCOMMIT);
    $conn->setAttribute(Doctrine_Core::ATTR_AUTOCOMMIT, FALSE);
    $conn->beginTransaction();
    $successful = false;
    try
    {
      $procedure->save($conn, $this->getLogger(), $this->getUser());
      $amount = $this->calculator->getAmountDue();
      $mail = new ProcedureMail($this->getContext(), $procedure, $amount);
      $env = $this->getContext()->getConfiguration()->getEnvironment();
      if($env == 'prod') {
        $this->getMailer()->send($mail); // TODO enable for prod
      } else {
        $this->getLogger()->log(sprintf('Mail to be sent: %s', $mail->toString()));
      }
      $conn->commit();
      $this->getLogger()->debug('Transaction commited');
      $successful = true;
    }
    catch (Exception $ex)
    {
      $this->getLogger()->emerg($ex);
      $this->getLogger()->debug('An exception occured during the save transaction, rolling back...');
      $conn->rollback();
      $this->getLogger()->debug('Roll back successful');
      $this->getLogger()->emerg($ex);
      $this->failed = true;
      $this->executeOverview($request);
      $this->setTemplate('overview');
    }
    $conn->setAttribute(Doctrine_Core::ATTR_AUTOCOMMIT, $old_transaction_type_attribute );
    
    if($successful) {
      $this->redirect($this->generateUrl('procedure_4_overview_saved'));
    }
  }

  /**
   *
   * @param sfRequest $request A request object
   */
  public function executeSaved (sfWebRequest $request)
  {
    $this->initilizeProcedure();
    $procedure = $this->getProcedure();
    $this->about_me = $procedure->getUserProfile();
    $this->participants = $procedure->getParticipants();
    $this->tents = $procedure->getTents();
    $this->saved = true;
    
    // TODO refactor to procedure or so
      $bookings = new Doctrine_Collection('Booking');
      $bookings->add($this->getUser()->getGuardUser()->getBooking());
      $payments = $this->getUser()->getGuardUser()->getBooking()->getPayments();
      $this->calculator = new PriceCalculator($bookings, $payments, $this->participants);
      
    $this->setTemplate('overview');
  }

  private function initilizeProcedure ()
  {
    $procedure = $this->getUser()->getAttribute('procedure');
    if(!$procedure instanceof Procedure) 
      $procedure = new Procedure($this->getUser()->getGuardUser(), $this->getLogger());
    $this->getUser()
      ->setAttribute('procedure', $procedure);
  }

  /**
   * @return Procedure
   */
  private function getProcedure ()
  {
    $procedure = $this->getUser()
      ->getAttribute('procedure');
    if (! $procedure instanceof Procedure)
    {
      throw new Exception('Procedure not initialized.');
    }
    return $procedure;
  }

  /**
   * @param sfWebRequest $request
   * @return boolean
   */
  private function processAboutMe (sfWebRequest $request)
  {
    $this->form = new AboutMeForm($this->getProcedure()
      ->getUserProfile());
    $this->form->bind($request->getParameter($this->form->getName()), $request->getFiles($this->form->getName()));
    //return true; // TODO Remove for prod
    if ($this->form->isValid())
    {
      $this->getProcedure()
        ->updateFromAboutMeForm($this->form);
      return true;
    }
    else
    {
      return false;
    }
  }

  private function processParticipants (sfWebRequest $request)
  {
    $this->getLogger()->debug(sprintf('Calling %s', __METHOD__));
    
    $this->form = new DynamicParticipantForm($this->getProcedure()
      ->getParticipants(), array(
      DynamicParticipantForm::OPTION_PARTICIPANT_DEFAULT_VALUES => $this->getProcedure()
      ->getParticipantDefaultValues(),
      DynamicParticipantForm::OPTION_LOGGER => $this->getLogger()));
    $this->form->addPreviouslyAddedForms($request->getParameter($this->form->getName())); 
    //$this->form->addForm(); 
    $this->form->bind($request->getParameter($this->form->getName()), $request->getFiles($this->form->getName()));
    // TODO Manipulate objects
    //return true; // TODO Remove for prod
    $this->getLogger()->debug(sprintf('Logging form values: %s', print_r($this->form->getValues(), true)));
    if ($this->form->isValid())
    {
      $this->getProcedure()
        ->updateFromDynamicParticipantForm($this->form);
      return true;
    }
    else
    {
      return false;
    }
  }

  private function processTents (sfWebRequest $request)
  {
    $participants = $this->getProcedure()->getParticipants();
    $num_participants_in_house = 0;
    $num_participants_in_tent = 0;
    // TODO refactor as method to procedure
    foreach($participants as $participant) {
      if($participant->getAccomodation() == 'h') {
        $num_participants_in_house++;
      } else {
        $num_participants_in_tent++;
      }
    }
    $this->num_participants_in_house = $num_participants_in_house;
    $this->num_participants_in_tent = $num_participants_in_tent;
    
    $this->form = new DynamicTentForm($this->getProcedure()
      ->getTents(), array(
      DynamicTentForm::OPTION_NUM_PARTICIPANTS_IN_HOUSE => $this->num_participants_in_house, DynamicTentForm::OPTION_NUM_PARTICIPANTS_IN_TENT => $this->num_participants_in_tent));
    $this->form->addPreviouslyAddedForms($request->getParameter($this->form->getName()));
    $this->form->bind($request->getParameter($this->form->getName()), $request->getFiles($this->form->getName()));
    // TODO Manipulate objects
    //return false; // TODO Remove for prod
    if ($this->form->isValid())
    {
      $this->getProcedure()
        ->updateFromDynamicTentForm($this->form);
      return true;
    }
    else
    {
      return false;
    }
  }
}
